using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace Client.UIHelper
{
    /// <summary>
    /// The BuyNowHelper Class is used by the BuyNowForm to handle the interface with the Serverprocessing
    /// class.  The server processing class handles the interaction with the web services.  BuyNowHelper
    /// implements methods that the BuyNowForm calls.  
    /// 
    /// The method HandlePayment generates the Paypal URL based on variables set 
    /// in APP.config and launchs a new IE window with the Paypal URL.  During this process a GUID is generated
    /// to be used as the Paypal invoice number.  The invoice number is also returned to the caller so it can be used 
    /// later on during the buy now web service processing to relate a Paypal transacation to a license request
    /// 
    /// The method Handleprocessing calls the Serverprocessing class and passes the invoice number as a parameter.  This initiates
    /// the polling to the Buy Now Web Service.  When an answer or timout is received the UI is notified using the registered 
    /// ProcessingFailed and ProcessingComplete events
    /// </summary>
    public class BuyNowHelper : IDisposable
    {
        #region private class variables

        //initialize the logger
        private string _requestedLicenseLevel;
        private string _requestedLicenseLevelPrice;
        private Form form;
        private Logger logger = new Logger(Application.StartupPath, "CCSClientLog.txt");

        //invoice is a unique GUID used in the construction of the Paypal URL, and also in the polling of the buy now web service
        //it is used to relate a Paypal transaction with a license request on the buy now web service
        private Guid m_guidInvoice;

        //this is used so we can pass the form handle through the serverProcessing class.
        //Because the web service calls are asynch, it is necessary to have this handle
        //so we can invoke the processingComplete and processingFailed events on the UI thread

        private string m_strInvoice;
        private Serverprocessing serverProcessing;

        #endregion

        //the public event handler for processing complete.  The buyNowForm registers a handler to this event.
        //This event is triggered when the serverProcessing class signals that processing has successfully completed
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<ProcessingCompletedEvent> _processingComplete;


        /// <summary>
        /// The private processing failed event handler
        /// </summary>
        private EventHandler<ProcessingFailedEvent> _processingFailed;

        public EventHandler<ProcessingCompletedEvent> ProcessingComplete
        {
            get { return _processingComplete; }
            set { _processingComplete = value; }
        }

        /// <summary>
        ///the public event handler for processing failed. The buyNowForm registers a handler to this event.
        ///This event is triggered when the severProcessing class signals that processing has successfully completed.
        ///The failure message is passed within the event args.  ProcessingFailedEventHandler is defined in the
        ///Serverprocessing class 
        /// </summary>
        public EventHandler<ProcessingFailedEvent> ProcessingFailed
        {
            get { return _processingFailed; }
            set { _processingFailed = value; }
        }

        #region constructor

        /// <summary>
        /// The constructor initializes the invoice variable to a new System.Guid.NewGuid
        /// and sets the private form variable
        /// </summary>
        /// <param name="formIn">A reference to the form using this class</param>
        public BuyNowHelper(Form formin)
        {
            Logger.Log("BuyNowHelper : Constructor : Beginning");
            //set the private for the calling form
            form = formin;

            //set invoice to a new GUID
            m_guidInvoice = Guid.NewGuid();

            Logger.Log("BuyNowHelper : Constructor : Completed");
        }

        #endregion

        #region public methods

        public string RequestedLicenseLevelPrice
        {
            get { return _requestedLicenseLevelPrice; }
            set { _requestedLicenseLevelPrice = value; }
        }

        public string RequestedLicenseLevel
        {
            get { return _requestedLicenseLevel; }
            set { _requestedLicenseLevel = value; }
        }

        public string Invoice
        {
            get { return m_strInvoice; }
            set { m_strInvoice = value; }
        }

        /// <summary>
        /// This method creates a new Paypal class and calls the HandleMethod method.  The Paypal
        /// class generates the Paypal URL, which is based on the invoice passed in.  When HandlePayment
        /// is called a new IE window is launched to this URL
        /// </summary>
        public void Handlepayment()
        {
            Logger.Log("BuyNowHelper : Handlepayment : Beginning");

            //create Paypal class passing in invoice as string
            var paypal = new Paypal(m_guidInvoice.ToString(), _requestedLicenseLevelPrice, form);

            //launch the new IE window to the Paypal URL
            paypal.Handlepayment();

            Logger.Log("BuyNowHelper : Handlepayment : Completed");
        }

        /// <summary>
        /// This methos starts the polling for the buy now web service.  The calling form handle, invoice string,
        /// and enumerated form type (defined in serverProcessing) are passed in.  The form handle is necessary so
        /// we can invoke the event handlers on the UI thread from the asynch web service calls.  Handleprocessing also registers the BuyNowHelper
        /// Event handlers with the signal processing class for ProcessingComplete and ProcessingFailed.
        /// </summary>
        public void Handleprocessing()
        {
            Logger.Log("BuyNowHelper : Handleprocessing : Beginning");
            var buyNowInfo = new BuyNowInfo(_requestedLicenseLevel, m_guidInvoice.ToString(), form, false);

            //create a new serverProcessing class passing in the calling form handle, invoice, and enum form type.
            serverProcessing = new Serverprocessing(buyNowInfo);

            //register the eventHandler ProcessingComplete of this class to the public event of
            //serverprocessingc
            serverProcessing.Processingcomplete += new EventHandler<ProcessingCompletedEvent>(SignalProcessingComplete);

            //register the eventHandler ProcessingFailed of this class to the public event of
            //serverprocessing.  The message is passed in the args.  ProcessingFailedEventHandler is
            //defined in Serverprocessing
            serverProcessing.Processingfailed += new EventHandler<ProcessingFailedEvent>(SignalProcessingFailed);

            //start the buyNowWeb service polling for a valid invoice
            serverProcessing.HandleBuyNow();


            Logger.Log("BuyNowHelper : Handleprocessing : Completed");
        }

        /// <summary>
        /// This function uses the serverProcessing class to process an invoice.  If all goes well we
        /// will receive a valid ProductKey back from the web service and be activated.
        /// </summary>
        /// <param name="invoice">This is the invoice number entered by the user.</param>
        public void HandleProcessingInvoice()
        {
            Logger.Log("BuyNowHelper : HandleProcessingInvoice : Beginning");

            if (m_strInvoice.Length > 0 && m_strInvoice != " ")
            {
                try
                {
                    var buyNowInfo = new BuyNowInfo(_requestedLicenseLevel, m_strInvoice, form, true);

                    //we pass in the invoice to send up in the web service, and also pass in
                    //the form handle from ActivateNowHelper.  This is used to invoke events on the Main UI thread.
                    //We pass in FormType so serverProcessing can know which constants to load depending on which 
                    //form is calling it.
                    serverProcessing = new Serverprocessing(buyNowInfo);

                    //register the eventHandler ProcessingComplete of this class to the public event of
                    //serverprocessing
                    serverProcessing.Processingcomplete += new EventHandler<ProcessingCompletedEvent>(SignalProcessingComplete);

                    //register the eventHandler ProcessingFailed of this class to the public event of
                    //serverprocessing.  The message is passed in the args.  ProcessingFailedEventHandler is
                    //defined in Serverprocessing
                    serverProcessing.Processingfailed += new EventHandler<ProcessingFailedEvent>(SignalProcessingFailed);

                    Logger.Log("BuyNowHelper : HandleProcessingInvoice : serverProcessing.HandleProcessing : Beginning");
                    //this call causes serverProcessing to launch the web service begin call
                    serverProcessing.HandleBuyNow();
                    Logger.Log("BuyNowHelper : HandleProcessingInvoice : serverProcessing.HandleProcessing : Completed");
                }
                catch (Exception ex)
                {
                    Logger.Log("BuyNowHelper : HandleProcessingInvoice : Exception : " + ex.Message);
                    string message = "An Error occurred while contacting the server. ";
                    SignalProcessingFailed(this, new ProcessingFailedEvent(message, form));
                    throw;
                }
                catch
                {
                    throw;
                }
            }

            Logger.Log("BuyNowHelper : HandleProcessingInvoice : Completed");
        }

        /// <summary>
        /// This method must be called to dipose of the resources used by server processing.  
        /// This is used when you want to close the form that initiated the begin processing call.
        /// If this is not called the web service asynch call will generate an exception.
        /// </summary> 
        public void Cancelprocessing()
        {
            Debug.WriteLine("Calling UIHelper dispose");

            Logger.Log("BuyNowHelper : Cancelprocessing : Beginning");

            //we only want to do this if the serverProcessing class has been initialized
            if (serverProcessing != null)
            {
                Logger.Log("BuyNowHelper : Cancelprocessing : serverProcessing.Cancelprocessing");
                serverProcessing.Cancelprocessing();
            }

            Logger.Log("BuyNowHelper : Cancelprocessing : Completed");
        }


        //This method fires this forms public event for processing complete.  This in turn
        //is registered with BuyNowForm
        private void SignalProcessingComplete(object sender, ProcessingCompletedEvent e)
        {
            ProcessingComplete(this, e);
        }

        //This method fires this forms public event for processing failed.  This in turn
        //is registered with BuyNowForm
        private void SignalProcessingFailed(object sender, ProcessingFailedEvent e)
        {
            ProcessingFailed(this, e);
        }

        #endregion

        // Implement IDispose

        #region IDisposable Members

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // Free other state (managed object)
                serverProcessing.Dispose();
                form.Dispose();
            }
            // Free your own state (unmanaged objects)

            // Set large field to null
        }

        // Use C# destructor syntax for finalization code
        ~BuyNowHelper()
        {
            Dispose(false);
        }
    }

    /// <summary>
    /// The class that contains all the information to be passed to the web service processing class
    /// ServerProcessing
    /// </summary>
    public class BuyNowInfo
    {
        private Form _formReference;
        private string _invoice;
        private Boolean _isProductkey;
        private string _licenseLevel;

        public BuyNowInfo(string licenseLevel, string invoice, Form form, bool isProductKey)
        {
            _licenseLevel = licenseLevel;
            _invoice = invoice;
            _formReference = form;
            _isProductkey = isProductKey;
        }

        public Form FormRef
        {
            get { return _formReference; }
        }

        public string LicenseLevel
        {
            get { return _licenseLevel; }
        }

        public string Invoice
        {
            get { return _invoice; }
        }

        public bool IsProductKey
        {
            get { return _isProductkey; }
        }
    }
}